package com.xiaopang.fitment.Utils;

import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.mail.MailProperties;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Component;

import java.time.Duration;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * 邮箱服务类
 */
@Component
public class EmailUtil {

    private final Random random = new Random();
    private final JavaMailSender mailSender;
    private final MailProperties mailProperties;

    @Autowired
    private RedisTemplate redisTemplate;
    /**
     * 验证码有效期，分钟
     */
    private static final int VERIFY_CODE_EXPIRE = 30;
    // 验证码缓存器(关闭程序将丢失)
    private static final Cache<String, String> verifyCodeCache;

    private static final Logger logger = LoggerFactory.getLogger(EmailUtil.class);

    static {
        verifyCodeCache = Caffeine.newBuilder()
                .initialCapacity(32)
                .maximumSize(5120)
                // 有效期 30分钟
                .expireAfterWrite(Duration.ofMinutes(VERIFY_CODE_EXPIRE))
                .build();
    }

    public EmailUtil(JavaMailSender mailSender, MailProperties mailProperties) {
        this.mailSender = mailSender;
        this.mailProperties = mailProperties;
    }

    /**
     * 发送邮箱验证码
     *
     * @param email 邮箱
     */
    public void sendEmailCode(String email) {
        String code = generateCode(6);
        SimpleMailMessage mailMessage = new SimpleMailMessage();
        mailMessage.setFrom(mailProperties.getUsername());
        // 邮箱标题
        mailMessage.setSubject("正在使用邮箱注册帐号，请查收校验码！");
        // 邮箱内容
        mailMessage.setText("您好，本次操作校验码为：" + code + " (此验证码" + VERIFY_CODE_EXPIRE + "分钟内有效！) 。您正在使用邮箱注册帐号，如非本人操作，请忽略。");
        // 收件人
        mailMessage.setTo(email);
        mailSender.send(mailMessage);
        if (logger.isInfoEnabled()) {
            logger.info("验证码发送成功：邮箱>>>{},验证码>>>{}", email, code);
        }
        // 存入缓存
        verifyCodeCache.put(email, code);

        redisTemplate.opsForValue().set(email, code, VERIFY_CODE_EXPIRE, TimeUnit.MINUTES);

    }

    /**
     * 获取验证码
     *
     * @param email 邮箱
     * @return 验证码，可选
     */
    public Optional<String> getVerifyCode(String email) {
        String code = verifyCodeCache.getIfPresent(email);
        String code2 = (String) redisTemplate.opsForValue().get(email);
        return Optional.ofNullable(code);
    }

    /**
     * 生成code
     *
     * @param codeLen code长度
     * @return
     */
    private String generateCode(int codeLen) {
        StringBuilder code = new StringBuilder();
        for (int i = 0; i < codeLen; i++) {
            // 0-9 随机取一个
            code.append(random.nextInt(10));
        }
        return code.toString();
    }

}
